import Obj3D from "../Poly/Obj3D.js";
import Scene from "../Poly/Scene.js";
import Arc from "./Arc-ba.js";
import Particle from "./Particle-ba.js";
import Round from "./Round-ba.js";
import { Vector3 } from "three";
import { CreateProgram } from "../Utils.js";

import Arcvert from "../../../public/shader/Arc.vert.js";
import Arcfrag from "../../../public/shader/Arc.frag.js";
import Particlevert from "../../../public/shader/Particle.vert.js";
import Particlefrag from "../../../public/shader/Particle.frag.js";
import Roundvert from "../../../public/shader/Round.vert.js";
import Roundfrag from "../../../public/shader/Round.frag.js";

const defAttr = () => ({
  canvas: null,

  //颜色均为[0-1]

  pointSize: 35, //整体的大小
  background_color: [0, 0, 0, 0], //背景颜色
  s: 0.01, //速度

  arc_color_on: [1, 1, 1, 0.5], //弧线内颜色
  arc_color_out: [0.3, 0.53, 1, 0.5], //弧线外颜色

  particle_color: [0.5, 1, 1, 0.5], //三角粒子颜色
  particle_count: 7, //每次触发的粒子数量
  particle_diff: [0.07, 0.05], //粒子生成时离中心点的距离 / 粒子向外扩散的距离

  round_color: [0.3, 0.53, 1, 0.5], //内圆颜色
});

//圆弧
export default class baClickEffect {
  constructor(attr) {
    Object.assign(this, defAttr(), attr);

    this.gl = null;
    this.scene = null;
    this.arc = null;
    this.particle = null;
    this.round = null;

    this.dataArr = [];

    this._init();
  }

  _init() {
    this._createObject();
  }

  //point:数组对象,[x, y]
  Trigger(point) {
    const [x, y] = this._getViewPosi(point[0], point[1]);
    this._createClickEffect(new Vector3(x, y, 0));
  }

  update() {
    const { dataArr } = this;

    for (let i = 0; i < dataArr.length; i++) {
      let { set, s, effectObj } = dataArr[i];

      if (set > 1) {
        //删除
        this._deleteData(i);
        i--;
        continue;
      }
      dataArr[i].set += s;
      effectObj.setUniform("u_Set", { value: dataArr[i].set });
    }
    this._draw();
  }

  setSize(w, h) {
    this.gl.viewport(0, 0, w, h);
  }

  _createObject() {
    const { canvas } = this;
    this.gl = canvas.getContext("webgl", { antialias: true });
    const { gl } = this;
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

    this.scene = new Scene({ gl: gl });
    const { scene } = this;
    scene.regProgram("arc", {
      program: CreateProgram(gl, Arcvert.getShader(), Arcfrag.getShader()),
      attribs: ["a_Position"],
      uniforms: ["u_Angle", "u_Set", "u_PointSize", "u_Line", "u_line_Color"],
    });
    scene.regProgram("particle", {
      program: CreateProgram(
        gl,
        Particlevert.getShader(),
        Particlefrag.getShader()
      ),
      attribs: ["a_Position"],
      uniforms: [
        "u_Opaque",
        "u_PointSize",
        "u_Angle",
        "u_Color",
        "u_Set",
        "u_Diff",
        "u_PosiMove",
        "u_Color",
      ],
    });
    scene.regProgram("round", {
      program: CreateProgram(gl, Roundvert.getShader(), Roundfrag.getShader()),
      attribs: ["a_Position"],
      uniforms: ["u_PointSize", "u_Color", "u_Set", "u_Margin"],
    });

    const {
      pointSize,
      arc_color_on,
      arc_color_out,
      round_color,
      particle_color,
      particle_count,
      particle_diff,
    } = this;
    this.arc = new Arc({
      gl: gl,
      program: "arc",
      pointSize: pointSize,
      color1: arc_color_out,
      color2: arc_color_on,
    });
    this.particle = new Particle({
      program: "particle",
      gl: gl,
      count: particle_count,
      diff: particle_diff,
      color: particle_color,
    });
    this.round = new Round({
      program: "round",
      gl: gl,
      pointSize: this.arc.pointSize,
      margin: this.arc.getInsideArcMargin(),
      color: round_color,
    });
  }

  _createClickEffect(point) {
    const { dataArr, scene, gl, arc, particle, round, s } = this;

    const effect = new Obj3D();
    const arcObj = arc.getElement(point);
    effect.add(gl, arcObj);

    const particleObj = particle.getElement(point);
    effect.add(gl, particleObj);

    const roundObj = round.getElement(point);
    effect.add(gl, roundObj);

    scene.add(effect);
    dataArr.push({
      set: 0,
      s: s,
      effectObj: effect,
    });
  }

  _deleteData(index) {
    const { dataArr, scene } = this;
    const { effectObj } = dataArr[index];
    scene.remove(effectObj);
    //console.log('剩余', scene.children.length, '个')
    dataArr.splice(index, 1);
  }

  _getViewPosi(x, y) {
    const { canvas } = this;
    const [hx, hy] = [canvas.width / 2, canvas.height / 2];
    const [cx, cy] = [(x - hx) / hx, -(y - hy) / hy];
    return [cx, cy];
  }

  _draw() {
    const { scene, background_color } = this;
    scene.draw(background_color);
  }
}
